home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Carousel
/
CAROUSEL.cdr
/
mactosh
/
utilprn
/
hpdeskje.sit
/
HPDJet ƒ
/
BatchPrint ƒ
/
BatchPrint.Pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1989-04-21
|
68KB
|
2,221 lines
{ 21.04.1989 amn (latest edit) }
{$U-} {don't automatically include "Pascal Textbook" units}
{$D+} {MacsBug symbols}
PROGRAM BatchPrint;
{ A program to print one or more spool files }
{ produced by the HPDJ printer driver. }
{ Authors: Ari Mujunen (amn@hutcs.hut.fi), }
{ Johan MyrÄen (jem@hutcs.hut.fi }
{ and Olli Arnberg (oar@hutcs.hut.fi). }
{ Copyright Ari Mujunen, Johan MyrÄen, Olli Arnberg 1989. }
{ You may redistribute this application (=application file, source files, }
{ documentation file(s), and the file 'Copyright and Source Offer') }
{ only _non-commercially_ and _in its entirety_. }
{ See the file 'BatchPrint Copyright' and/or documentation for details. }
{ Acknowledgements: Special thanks to Mr. Paul DuBois and Mr. Owen Hartnett }
{ for the TransSkel 2.0 application skeleton. }
{ Change history: }
{ Version Date Who Why }
{ 0.0 31.03.1989 amn Original version. }
{ 02.04.1989 amn Windows, menus. }
{ 05.04.1989 amn,oar More windows, menus. }
{ 11.04.1989 amn Printing. }
{ 12.04.1989 amn Cleaning up. }
{ 13.04.1989 amn Settings and Page menus. }
{ 14.04.1989 jem Scroll bars. }
{ 15.04.1989 amn,jem More scroll bars. }
{ 16.04.1989 amn,jem Goto Page, Scale Preview and general tidying. }
{ 17.04.1989 amn "No windows" menu state. }
{ 20.04.1989 amn Print only pages needed. }
{ 21.04.1989 amn,jem Print All didn't work. }
{$B+} {Bundle bit on, we have icons etc. }
{$T APPL^89s} {File type 'APPL', creator '^89s'.}
{$R BatchPrint.Rsrc} {Identify resource file.}
{$U TransSkel} {Unit 'TransSkel' is found in the file 'TransSkel'.}
USES
MemTypes,
QuickDraw,
OSIntf,
ToolIntf,
PackIntf,
MacPrint,
TransSkel;
CONST
cMagicalWidthOfScrollBars = 16; {pixels as required by WDEF 0}
cViewScalePercentageDefault = 100;
cNumberOfPixelsAroundPage= 16;
{ Resource id's: }
{ 'STR ': }
cStringAboutBatchPrint = 128;
cStringNumberOfPages = 129;
cStringPage = 130;
cStringWindowTitleAt100Percent = 131;
cStringWindowTitleAtOtherPercentages = 132;
cStringUnderMinimum = 133;
cStringOverMaximum = 134;
{ 'MENU': }
cMenuFirstId = 128;
{ 'ALRT': }
cAlertAboutBatchPrint = 128;
cAlertNoMemoryForWindows = 129;
cAlertFileError = 130;
cAlertPrintError = 131;
cAlertScalingPercentageOutOfBounds = 134;
{ 'WIND': }
cWindowOrdinary = 128;
cWindowZoomable = 129;
{ 'DLOG': }
cDialogScalePreview = 132;
cDialogGotoPage = 133;
{ Menu item numbers: }
cFileOpen = 1;
cFileClose = 3;
cFileCloseAll = 4;
cFilePageSetup = 6;
cFilePageSetupAll = 7;
cFilePrint = 8;
cFilePrintAll = 9;
cFileQuit = 11;
cEditUndo = 1;
cEditCut = 3;
cEditCopy = 4;
cEditPaste = 5;
cEditClear = 6;
cViewInformation = 1;
cViewContents = 2;
cViewScalePreview = 4;
cSettingsUsePrinterSpacing = 1;
cSettingsDisableFontScaling = 2;
cPagePrevious = 1;
cPageNext = 2;
cPageFirst = 4;
cPageLast = 5;
cPageGotoPage = 7;
cPagePageNumberItem = 8;
{ General dialog button item numbers: }
cOkButton = 1;
cCancelButton = 2;
{ Scale Preview Dialog items: }
cDITScalePercentage = 4;
{ Goto Page Dialog items: }
cDITPageNumber = 4;
TYPE
tWindowRelatedInfo=
RECORD
rSpoolFileHeader: TPfHeader; {must be first; read directly from file}
rOriginalPageRect: Rect;
rSFReply: SFReply;
rViewMenuSelectionForThisWindow: Integer;
rViewSize: ARRAY [cViewInformation..cViewContents] OF Rect;
rViewScalePreviewPercentage: Integer;
rUsePrinterSpacing: Boolean;
rDisableFontScaling: Boolean;
rPageNumber: Integer;
rVerticalScrollControl,
rHorizontalScrollControl: ControlHandle;
END;
tpWindowRelatedInfo= ^tWindowRelatedInfo;
thWindowRelatedInfo= ^tpWindowRelatedInfo;
tMenuEnumeration=(
eFile,
eEdit,
eView,
eSettings,
ePage
);
VAR
{ Global variables. }
vMenu: ARRAY [tMenuEnumeration] OF MenuHandle;
vHas128KROMs: Boolean;
vNumberOfOurOpenWindows: Integer;
{ Global settings. }
vViewMenuSelectionDefault: Integer;
vViewScalePercentageDefault: Integer;
vSettingsUsePrinterSpacing: Boolean;
vSettingsDisableFontScaling: Boolean;
{ For pOurGetPicProc. }
vGlobalSpoolFileRefNumDuringOnePageUpdate: Integer;
{ Instructions from the Finder. }
vWhatFinderToldUsToDo: Integer;
vNumberOfAppFiles: Integer;
{ Auxiliary variables for the main program. }
vMenuEnumeration: tMenuEnumeration;
hString: StringHandle;
successful: Boolean;
i: Integer;
theAppFile: AppFile;
romVersion: Integer;
machineType: Integer;
PROCEDURE pErrorAlert(theAlert: Integer);
VAR
buttonClicked: Integer;
BEGIN
buttonClicked := StopAlert(theAlert, NIL);
END; {pErrorAlert}
PROCEDURE pFileErrorAlert(
theAlert: Integer;
retCode: OSErr;
fileName: Str255
);
VAR
errorNumberAsString: Str255;
BEGIN
NumToString(Longint(retCode), errorNumberAsString);
ParamText(errorNumberAsString, fileName, '', '');
pErrorAlert(theAlert);
END; {pFileErrorAlert}
PROCEDURE pPrintErrorAlert(
theAlert: Integer;
retCode: OSErr
);
VAR
errorNumberAsString: Str255;
BEGIN
NumToString(Longint(retCode), errorNumberAsString);
ParamText(errorNumberAsString, '', '', '');
pErrorAlert(theAlert);
END; {pPrintErrorAlert}
FUNCTION fParametrizeSTR(
strId: Integer;
stringUsedIfResNotFound: Str255;
p0,
p1: Str255
) : Str255;
VAR
hString: StringHandle;
result: Str255;
i: Integer;
BEGIN
hString := GetString(strId);
IF hString = NIL THEN
result := stringUsedIfResNotFound
ELSE
result := hString^^;
i := Pos('^0', result);
IF i > 0 THEN
BEGIN
Delete(result, i, 2);
Insert(p0, result, i);
END;
i := Pos('^1', result);
IF i > 0 THEN
BEGIN
Delete(result, i, 2);
Insert(p1, result, i);
END;
fParametrizeSTR := result;
END; {fParametrizeSTR}
PROCEDURE pDoAboutBatchPrint;
VAR
buttonClicked: Integer;
BEGIN
buttonClicked := Alert(cAlertAboutBatchPrint, NIL);
END; {pDoAboutBatchPrint}
CONST
cPageNumberBoxPart = 5; {1/5 th part of horizontal scroller for page number}
PROCEDURE pCalcHorizontalScrollRect(theWindow: WindowPtr; VAR r: Rect);
VAR
width: Integer;
BEGIN
r := theWindow^.portRect;
r.right := r.right - cMagicalWidthOfScrollBars + 2;
r.left := r.left - 1;
r.bottom := r.bottom + 1;
r.top := r.bottom - cMagicalWidthOfScrollBars;
width := (r.right - r.left) DIV cPageNumberBoxPart;
r.right := r.right - width;
END; {pCalcHorizontalScrollRect}
PROCEDURE pCalcPageNumberRect(theWindow: WindowPtr; VAR r: Rect);
VAR
width: Integer;
BEGIN
r := theWindow^.portRect;
r.right := r.right - cMagicalWidthOfScrollBars + 2;
r.left := r.left - 1;
r.bottom := r.bottom + 1;
r.top := r.bottom - cMagicalWidthOfScrollBars;
width := (r.right - r.left) DIV cPageNumberBoxPart;
r.left := r.right - width;
END; {pCalcHorizontalScrollRect}
PROCEDURE pCalcVerticalScrollRect(theWindow: WindowPtr; VAR r: Rect);
BEGIN
r := theWindow^.portRect;
r.right := r.right + 1;
r.left := r.right - cMagicalWidthOfScrollBars;
r.bottom := r.bottom - cMagicalWidthOfScrollBars + 2;
r.top := r.top - 1;
END; {pCalcVerticalScrollRect}
PROCEDURE pCalcDocumentRect(theWindow: WindowPtr; VAR docRect: Rect);
{VAR}
{savePort: GrafPtr;}
BEGIN
{This does not work for hidden windows:}
{GetPort(savePort);}
{SetPort(theWindow);}
{docRect := WindowPeek(theWindow)^.contRgn^^.rgnBBox;}
{GlobalToLocal(docRect.topLeft);}
{GlobalToLocal(docRect.botRight);}
docRect := theWindow^.portRect;
docRect.right :=
docRect.right - cMagicalWidthOfScrollBars + 1;
docRect.bottom :=
docRect.bottom - cMagicalWidthOfScrollBars + 1;
{SetPort(savePort);}
END; {pCalcDocumentRect}
PROCEDURE pCalcScaledPageDrawingRect(
vhWindowRelatedInfo: thWindowRelatedInfo
);
VAR
dstRect: Rect;
r1, r2: Rect;
BEGIN
dstRect := vhWindowRelatedInfo^^.rOriginalPageRect;
SetRect(r1, 0, 0, 100, 100);
SetRect(r2, 0, 0, vhWindowRelatedInfo^^.rViewScalePreviewPercentage, 0);
r2.bottom := r2.right;
MapRect(dstRect, r1, r2);
vhWindowRelatedInfo^^.rViewSize[cViewContents] := dstRect;
END; {pCalcScaledPageDrawingRect}
PROCEDURE pUpdateWindow(resized: Boolean); FORWARD;
PROCEDURE pScrollWindow(dh, dv: Integer; theScroll: ControlHandle);
VAR
vScrollingRect: Rect;
hUpdateRgn: RgnHandle;
saveVisRgn: RgnHandle;
theWindow: WindowPtr;
BEGIN
IF (dh=0) AND (dv=0) THEN
Exit;
hUpdateRgn := NewRgn;
IF hUpdateRgn = NIL THEN
BEGIN
pErrorAlert(cAlertNoMemoryForWindows); {??? no memory for update...}
Exit;
END;
pCalcDocumentRect(theScroll^^.contrlOwner, vScrollingRect);
ScrollRect(vScrollingRect, -dh, -dv, hUpdateRgn);
{ Minor modifications to visRgn before misusing our update proc. }
GetPort(theWindow);
saveVisRgn := theWindow^.visRgn;
theWindow^.visRgn := hUpdateRgn;
pUpdateWindow( {resized=>} False);
theWindow^.visRgn := saveVisRgn;
DisposeRgn(hUpdateRgn);
END; {pScrollWindow}
PROCEDURE pHorizontalScrollAction(
theScroll: ControlHandle;
partCode: Integer
);
VAR
docRect: Rect;
vDelta: Integer;
savedValue: Integer;
BEGIN
pCalcDocumentRect(theScroll^^.contrlOwner, docRect);
vDelta := (docRect.right - docRect.left) DIV 10; {one tenth of width}
CASE partCode OF
inUpButton: vDelta := -vDelta;
inDownButton: vDelta := vDelta;
inPageUp: vDelta := -9*vDelta;
inPageDown: vDelta := 9*vDelta;
OTHERWISE vDelta := 0;
END;
{ Let Control Manager do "endpoint bumping". }
savedValue := GetCtlValue(theScroll);
SetCtlValue(theScroll, savedValue + vDelta);
vDelta := GetCtlValue(theScroll) - savedValue;
pScrollWindow(vDelta, 0, theScroll);
END; {pHorizontalScrollAction}
PROCEDURE pVerticalScrollAction(
theScroll: ControlHandle;
partCode: Integer
);
VAR
docRect: Rect;
vDelta: Integer;
savedValue: Integer;
BEGIN
pCalcDocumentRect(theScroll^^.contrlOwner, docRect);
vDelta := (docRect.bottom - docRect.top) DIV 10; {one tenth of height}
CASE partCode OF
inUpButton: vDelta := -vDelta;
inDownButton: vDelta := vDelta;
inPageUp: vDelta := -9*vDelta;
inPageDown: vDelta := 9*vDelta;
OTHERWISE vDelta := 0;
END;
{ Let Control Manager do "endpoint bumping". }
savedValue := GetCtlValue(theScroll);
SetCtlValue(theScroll, savedValue + vDelta);
vDelta := GetCtlValue(theScroll) - savedValue;
pScrollWindow(0, vDelta, theScroll);
END; {pVerticalScrollAction}
PROCEDURE pSetScrollBarLimits(theWindow: WindowPtr);
VAR
vhWindowRelatedInfo: thWindowRelatedInfo;
savedState: SignedByte;
pageRect: Rect;
docRect: Rect;
maximumOrigin: Point;
BEGIN
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
IF vHas128KRoms THEN
savedState := HGetState(Handle(vhWindowRelatedInfo))
ELSE
savedState := Ptr(Handle(vhWindowRelatedInfo)^)^;
HLock(Handle(vhWindowRelatedInfo));
WITH vhWindowRelatedInfo^^ DO
BEGIN
pageRect := rViewSize[rViewMenuSelectionForThisWindow];
{ Reveal a part of grey background. }
InsetRect(pageRect,
-cNumberOfPixelsAroundPage,
-cNumberOfPixelsAroundPage
);
pCalcDocumentRect(theWindow, docRect);
maximumOrigin.v := pageRect.bottom - (docRect.bottom - docRect.top);
IF maximumOrigin.v < pageRect.top THEN
maximumOrigin.v := pageRect.top;
maximumOrigin.h := pageRect.right - (docRect.right - docRect.left);
IF maximumOrigin.h < pageRect.left THEN
maximumOrigin.h := pageRect.left;
SetCtlMin(rVerticalScrollControl, pageRect.top);
SetCtlMax(rVerticalScrollControl, maximumOrigin.v);
SetCtlMin(rHorizontalScrollControl, pageRect.left);
SetCtlMax(rHorizontalScrollControl, maximumOrigin.h);
END; {WITH}
IF vHas128KRoms THEN
HSetState(Handle(vhWindowRelatedInfo), savedState)
ELSE
Ptr(Handle(vhWindowRelatedInfo)^)^ := savedState;
END; {pSetScrollBarLimits}
TYPE
tProgramState=(
eNoOurWindowsOpen,
eAtLeastOneOurWindowOpen
);
PROCEDURE pChangeViewMenuAccordingToWindow(theWindow: WindowPtr); FORWARD;
PROCEDURE pChangeSettingsMenuAccordingToWindow(theWindow: WindowPtr); FORWARD;
PROCEDURE pMenusToState(vProgramState: tProgramState);
BEGIN
CASE vProgramState OF
eNoOurWindowsOpen:
BEGIN
DisableItem(vMenu[eFile], cFileClose);
DisableItem(vMenu[eFile], cFileCloseAll);
DisableItem(vMenu[eFile], cFilePageSetup);
DisableItem(vMenu[eFile], cFilePageSetupAll);
DisableItem(vMenu[eFile], cFilePrint);
DisableItem(vMenu[eFile], cFilePrintAll);
EnableItem(vMenu[eEdit], cEditUndo);
EnableItem(vMenu[eEdit], cEditCut);
EnableItem(vMenu[eEdit], cEditCopy);
EnableItem(vMenu[eEdit], cEditPaste);
EnableItem(vMenu[eEdit], cEditClear);
pChangeViewMenuAccordingToWindow(NIL);
pChangeSettingsMenuAccordingToWindow(NIL);
DisableItem(vMenu[ePage], cPagePrevious);
DisableItem(vMenu[ePage], cPageNext);
DisableItem(vMenu[ePage], cPageFirst);
DisableItem(vMenu[ePage], cPageLast);
DisableItem(vMenu[ePage], cPageGotoPage);
END;
eAtLeastOneOurWindowOpen:
BEGIN
EnableItem(vMenu[eFile], cFileClose);
EnableItem(vMenu[eFile], cFileCloseAll);
EnableItem(vMenu[eFile], cFilePageSetup);
EnableItem(vMenu[eFile], cFilePageSetupAll);
EnableItem(vMenu[eFile], cFilePrint);
EnableItem(vMenu[eFile], cFilePrintAll);
DisableItem(vMenu[eEdit], cEditUndo);
DisableItem(vMenu[eEdit], cEditCut);
DisableItem(vMenu[eEdit], cEditCopy);
DisableItem(vMenu[eEdit], cEditPaste);
DisableItem(vMenu[eEdit], cEditClear);
EnableItem(vMenu[ePage], cPagePrevious);
EnableItem(vMenu[ePage], cPageNext);
EnableItem(vMenu[ePage], cPageFirst);
EnableItem(vMenu[ePage], cPageLast);
EnableItem(vMenu[ePage], cPageGotoPage);
END;
END;
END; {pMenusToState}
PROCEDURE pRetitleWindow(theWIndow: WindowPtr);
VAR
vhWindowRelatedInfo: thWindowRelatedInfo;
name: Str255;
scalePercentage: Integer;
scalePercentageAsString: Str255;
titleString: Str255;
BEGIN
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
name := vhWindowRelatedInfo^^.rSFReply.fName;
scalePercentage := vhWindowRelatedInfo^^.rViewScalePreviewPercentage;
NumToString(Longint(scalePercentage), scalePercentageAsString);
IF scalePercentage = 100 THEN
titleString := fParametrizeSTR(
cStringWindowTitleAt100Percent,
'^0',
name,
scalePercentageAsString
)
ELSE
titleString := fParametrizeSTR(
cStringWindowTitleAtOtherPercentages,
'^0 at ^1%',
name,
scalePercentageAsString
);
SetWTitle(theWindow, titleString);
END; {pRetitleWindow}
FUNCTION fCreateWindow(
VAR theWindow: WindowPtr;
vSFReply: SFReply
) : Boolean;
LABEL
closeFile;
CONST
cDropDown= 30;
cDropRight= 20;
VAR
previousFrontWindow: WindowPtr;
newTopLeft: Point;
vhWindowRelatedInfo: thWindowRelatedInfo;
hScrollBar: ControlHandle;
vScrollBarRect: Rect;
windowRelatedInfoSuccessfullyRead: Boolean;
fileRefNum: Integer;
numberOfBytes: LongInt;
retCode: OSErr;
BEGIN
previousFrontWindow := FrontWindow;
{ Create (an invisible) window from appropriate template }
{ and let it be backmost (to prevent generating activate events now). }
IF vHas128KROMs THEN
theWindow := GetNewWindow(cWindowZoomable, NIL, {behind=>} NIL)
ELSE
theWindow := GetNewWindow(cWindowOrdinary, NIL, {behind=>} NIL);
IF theWindow = NIL THEN
BEGIN
pErrorAlert(cAlertNoMemoryForWindows);
fCreateWindow := False;
Exit;
END;
{ Drop window nicely below the current topmost window. }
WITH newTopLeft DO
IF previousFrontWindow = NIL THEN
BEGIN
v := -theWindow^.portBits.bounds.top;
h := -theWindow^.portBits.bounds.left;
END
ELSE
BEGIN
v := -previousFrontWindow^.portBits.bounds.top + cDropDown;
h := -previousFrontWindow^.portBits.bounds.left + cDropRight;
END;
{ Move only if top left is visible on screen. }
IF PtInRect(newTopLeft, screenBits.bounds) THEN
MoveWindow(theWindow, newTopLeft.h, newTopLeft.v, {front=>} True)
ELSE
; {leaves the window in the position defined in the WIND resource}
{ Create our additional storage for this window. }
vhWindowRelatedInfo := thWindowRelatedInfo(NewHandle(Sizeof(tWindowRelatedInfo)));
IF vhWindowRelatedInfo = NIL THEN
BEGIN
pErrorAlert(cAlertNoMemoryForWindows);
DisposeWindow(theWindow);
fCreateWindow := False;
Exit;
END;
SetWRefCon(theWindow, Longint(vhWindowRelatedInfo));
{ Create scroll bars. }
pCalcHorizontalScrollRect(theWindow, vScrollBarRect);
hScrollBar := NewControl(
theWindow,
vScrollBarRect,
'',
{visible=>} False,
0,0,0,
scrollBarProc,
{refCon=>} 0
);
IF hScrollBar = NIL THEN
BEGIN
pErrorAlert(cAlertNoMemoryForWindows);
DisposHandle(Handle(vhWindowRelatedInfo));
DisposeWindow(theWindow);
fCreateWindow := False;
Exit;
END;
SetCtlAction(hScrollBar, @pHorizontalScrollAction);
vhWindowRelatedInfo^^.rHorizontalScrollControl := hScrollBar;
pCalcVerticalScrollRect(theWindow, vScrollBarRect);
hScrollBar := NewControl(
theWindow,
vScrollBarRect,
'',
{visible=>} False,
0,0,0,
scrollBarProc,
{refCon=>} 0
);
IF hScrollBar = NIL THEN
BEGIN
pErrorAlert(cAlertNoMemoryForWindows);
{ No need to dispose controls created this far (IM I-321). }
DisposHandle(Handle(vhWindowRelatedInfo));
DisposeWindow(theWindow);
fCreateWindow := False;
Exit;
END;
SetCtlAction(hScrollBar, @pVerticalScrollAction);
vhWindowRelatedInfo^^.rVerticalScrollControl := hScrollBar;
{ Set viewing way from global defaults. }
vhWindowRelatedInfo^^.rViewMenuSelectionForThisWindow :=
vViewMenuSelectionDefault;
vhWindowRelatedInfo^^.rViewScalePreviewPercentage :=
vViewScalePercentageDefault;
vhWindowRelatedInfo^^.rUsePrinterSpacing := vSettingsUsePrinterSpacing;
vhWindowRelatedInfo^^.rDisableFontScaling := vSettingsDisableFontScaling;
vhWindowRelatedInfo^^.rPageNumber := 1;
{ Set file name etc., read spool file header. }
vhWindowRelatedInfo^^.rSFReply := vSFReply;
windowRelatedInfoSuccessfullyRead := False;
HLock(Handle(vhWindowRelatedInfo));
WITH vhWindowRelatedInfo^^.rSFReply DO
BEGIN
retCode := FSOpen(fName, vRefNum, fileRefNum);
IF retCode = noErr THEN
BEGIN
{ Read print file header from start of the file. }
retCode := SetFPos(
fileRefNum,
fsFromStart,
0
);
IF retCode <> noErr THEN
BEGIN
pFileErrorAlert(cAlertFileError, retCode, fName);
GOTO closeFile;
END;
numberOfBytes := Sizeof(TPfHeader);
retCode := FSRead(
fileRefNum,
numberOfBytes,
Ptr(vhWindowRelatedInfo^)
);
IF retCode <> noErr THEN
BEGIN
pFileErrorAlert(cAlertFileError, retCode, fName);
GOTO closeFile;
END;
windowRelatedInfoSuccessfullyRead := True;
closeFile:
retCode := FSClose(fileRefNum);
END
ELSE
BEGIN
pFileErrorAlert(cAlertFileError, retCode, fName);
END;
END; {WITH}
IF NOT windowRelatedInfoSuccessfullyRead THEN
BEGIN
{ No need to dispose controls created this far (IM I-321). }
DisposHandle(Handle(vhWindowRelatedInfo));
DisposeWindow(theWindow);
fCreateWindow := False;
Exit;
END;
{ Quite a surprising place to set document sizes for all different }
{ viewing alternatives (currently cViewInformation/cViewContents). }
WITH vhWindowRelatedInfo^^ DO
BEGIN
{ Info will require as much space as the initial window is. }
pCalcDocumentRect(theWindow, rViewSize[cViewInformation]);
rViewSize[cViewInformation].bottom :=
rViewSize[cViewInformation].bottom - 2*cNumberOfPixelsAroundPage;
rViewSize[cViewInformation].right :=
rViewSize[cViewInformation].right - 2*cNumberOfPixelsAroundPage;
{ Contents according to page rect when spool file created. }
rOriginalPageRect := rSpoolFileHeader.Print.PrInfo.rPage;
pCalcScaledPageDrawingRect(vhWindowRelatedInfo); {changes rViewSize[cViewContents]}
pSetScrollBarLimits(theWindow);
SetCtlValue(rVerticalScrollControl, -cNumberOfPixelsAroundPage); {top}
SetCtlValue(rHorizontalScrollControl, -cNumberOfPixelsAroundPage); {left}
END; {WITH}
HUnlock(Handle(vhWindowRelatedInfo));
pRetitleWindow(theWindow);
SelectWindow(theWindow);
ShowWindow(theWindow);
IF vNumberOfOurOpenWindows <= 0 THEN
pMenusToState(eAtLeastOneOurWindowOpen);
vNumberOfOurOpenWindows := vNumberOfOurOpenWindows + 1;
fCreateWindow := windowRelatedInfoSuccessfullyRead;
END; {fCreateWindow}
PROCEDURE pDisposeAllStructuresRelatedToThisWindow(theWindow: WindowPtr);
VAR
vhWindowRelatedInfo: thWindowRelatedInfo;
BEGIN
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
IF vhWindowRelatedInfo <> NIL THEN
IF GetHandleSize(Handle(vhWindowRelatedInfo)) = Sizeof(tWindowRelatedInfo) THEN
BEGIN
DisposHandle(Handle(vhWindowRelatedInfo));
DisposeWindow(theWindow);
{ DisposeWindow will KillControls (IM I-321).}
END;
END; {pDisposeAllStructuresRelatedToThisWindow}
PROCEDURE pDisposeAllStructuresRelatedToCurrentWindow;
VAR
theWindow: WindowPtr;
BEGIN
GetPort(theWindow); {TransSkel makes the window to be deleted current.}
pDisposeAllStructuresRelatedToThisWindow(theWindow);
END; {pDisposeAllStructuresRelatedToCurrentWindow}
PROCEDURE pInvalidateAllOfWindow(theWindow: WindowPtr);
VAR
savePort: GrafPtr;
contentRegionInLocalCoordinates: RgnHandle;
BEGIN
GetPort(savePort);
SetPort(theWindow);
contentRegionInLocalCoordinates := NewRgn;
CopyRgn(WindowPeek(theWindow)^.contRgn, contentRegionInLocalCoordinates);
OffsetRgn(contentRegionInLocalCoordinates,
theWindow^.portBits.bounds.left,
theWindow^.portBits.bounds.top
);
InvalRgn(contentRegionInLocalCoordinates); {must be redrawn}
DisposeRgn(contentRegionInLocalCoordinates);
SetPort(savePort);
END; {pInvalidateAllOfWindow}
PROCEDURE pMouseInWindow(
thePoint: Point;
theTime: Longint;
theMods: Integer
);
VAR
theWindow: WindowPtr;
theControl: ControlHandle;
vControlPartCode: Integer;
vNewCtlValue, vOldCtlValue: Integer;
vhWindowRelatedInfo: thWindowRelatedInfo;
BEGIN
GetPort(theWindow);
vControlPartCode := FindControl(thePoint, theWindow, theControl);
IF vControlPartCode = 0 THEN
Exit;
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
IF vControlPartCode = inThumb THEN
BEGIN
vOldCtlValue := GetCtlValue(theControl);
vControlPartCode := TrackControl(theControl, thePoint, NIL);
IF theControl = vhWindowRelatedInfo^^.rHorizontalScrollControl THEN
pScrollWindow(
GetCtlValue(theControl) - vOldCtlValue,
0,
theControl
)
ELSE IF theControl = vhWindowRelatedInfo^^.rVerticalScrollControl THEN
pScrollWindow(
0,
GetCtlValue(theControl) - vOldCtlValue,
theControl
)
ELSE
;
END {IF inThumb}
ELSE
vControlPartCode := TrackControl(
theControl,
thePoint,
POINTER(-1) {uses the procedure set into the control record }
);
END; {pMouseInWindow}
PROCEDURE pUpdateWindowInformation(
theWindow: WindowPtr; {for convenience; must be current GrafPort}
vhWindowRelatedInfo: thWindowRelatedInfo; {must be locked}
needErasing: Boolean
);
VAR
vString: Str255;
BEGIN
IF needErasing THEN
EraseRgn(theWindow^.visRgn);
MoveTo(30, 10);
DrawString(vhWindowRelatedInfo^^.rSFReply.fName);
MoveTo(30, 30);
NumToString(
LongInt(vhWindowRelatedInfo^^.rSpoolFileHeader.pfPgDir.iPages),
vString
);
vString := fParametrizeSTR(
cStringNumberOfPages,
'Number Of Pages: ^0',
vString,
''
);
DrawString(vString);
END; {pUpdateWindowInformation}
PROCEDURE pOurGetPicProc(
dataPtr: Ptr;
byteCount: Integer
);
VAR
longByteCount: Longint;
i: Integer;
retCode: OSErr;
BEGIN
longByteCount := Longint(byteCount);
retCode := FSRead(
vGlobalSpoolFileRefNumDuringOnePageUpdate,
longByteCount,
dataPtr
);
IF retCode <> noErr THEN
BEGIN
pFileErrorAlert(cAlertFileError, retCode, '???');
FOR i:=1 TO byteCount DO
BEGIN
dataPtr^ := -1; { $FF, end of picture }
Longint(dataPtr) := Succ(Longint(dataPtr));
END;
END;
END; {pOurGetPicProc}
PROCEDURE pUpdateWindowPageContents(
theWindow: WindowPtr; {for convenience; must be current GrafPort}
vhWindowRelatedInfo: thWindowRelatedInfo; {must be locked}
pageNumber: Integer;
needErasing: Boolean;
scalingForScreen: Boolean
);
LABEL
closeFile,
disposePicAndcloseFile;
VAR
spoolFileRefNum: Integer;
numberOfBytes: Longint;
handleToPagePicture: PicHandle;
stdProcs: QDProcs;
wePerformedTheCustomization: Boolean;
savedGetPicProc: QDPtr;
dstRect: Rect;
retCode: OSErr;
BEGIN
IF needErasing THEN
EraseRgn(theWindow^.visRgn);
WITH vhWindowRelatedInfo^^ DO
BEGIN
retCode := FSOpen(rSFReply.fName, rSFReply.vRefNum, spoolFileRefNum);
IF retCode = noErr THEN
BEGIN
{ Position to the start of the page. }
retCode := SetFPos(
spoolFileRefNum,
fsFromStart,
rSpoolFileHeader.pfPgDir.lPgPos[pageNumber]
);
IF retCode <> noErr THEN
BEGIN
pFileErrorAlert(cAlertFileError, retCode, rSFReply.fName);
GOTO closeFile;
END;
numberOfBytes := Sizeof(Picture);
handleToPagePicture := PicHandle(NewHandle(numberOfBytes));
IF handleToPagePicture = NIL THEN
BEGIN
pErrorAlert(cAlertNoMemoryForWindows); {??? no mem. for update...}
GOTO closeFile;
END;
retCode := FSRead(
spoolFileRefNum,
numberOfBytes,
Ptr(handleToPagePicture^)
);
IF retCode <> noErr THEN
BEGIN
pFileErrorAlert(cAlertFileError, retCode, rSFReply.fName);
GOTO disposePicAndcloseFile;
END;
{ Install a new picture retrieval procedure to read directly from disk. }
IF theWindow^.grafProcs = NIL THEN
BEGIN { not customized yet }
SetStdProcs(stdProcs);
stdProcs.getPicProc := @pOurGetPicProc;
theWindow^.grafProcs := @stdProcs;
wePerformedTheCustomization := True;
END
ELSE
BEGIN { already customized (by Printing Manager?) }
savedGetPicProc := theWindow^.grafProcs^.getPicProc;
theWindow^.grafProcs^.getPicProc := @pOurGetPicProc;
wePerformedTheCustomization := False;
END;
IF vHas128KROMs THEN
BEGIN
SetFractEnable(rUsePrinterSpacing);
SetFScaleDIsable(rDisableFontScaling);
END;
vGlobalSpoolFileRefNumDuringOnePageUpdate := spoolFileRefNum;
{ Draw the page picture from disk. }
IF scalingForScreen THEN
dstRect := rViewSize[cViewContents]
ELSE
dstRect := rOriginalPageRect;
DrawPicture(
handleToPagePicture,
dstRect
);
vGlobalSpoolFileRefNumDuringOnePageUpdate := 0;
IF vHas128KROMs THEN
BEGIN
SetFractEnable(False);
SetFScaleDIsable(False);
END;
IF wePerformedTheCustomization THEN
theWindow^.grafProcs := NIL
ELSE
theWindow^.grafProcs^.getPicProc := savedGetPicProc;
disposePicAndcloseFile:
DisposHandle(Handle(handleToPagePicture));
closeFile:
retCode := FSClose(spoolFileRefNum);
END {IF opened successfully}
ELSE
BEGIN
pFileErrorAlert(cAlertFileError, retCode, rSFReply.fName);
END;
END; {WITH}
END; {pUpdateWindowPageContents}
PROCEDURE pUpdateWindow { (forward) (resized: Boolean)} ;
VAR
theWindow: WindowPtr;
vhWindowRelatedInfo: thWindowRelatedInfo;
watchCursorHandle: CursHandle;
vhHorizontalScroll: ControlHandle;
vhVerticalScroll: ControlHandle;
vScrollRect: Rect;
pageNumberAsString: Str255;
lastPageNumberAsString: Str255;
saveClip: RgnHandle;
docRect: Rect;
pageRect: Rect;
docRgn: RgnHandle;
pageRgn: RgnHandle;
theRgn: RgnHandle;
BEGIN
GetPort(theWindow);
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
{ Cursor as a wristwatch. }
watchCursorHandle := GetCursor(watchCursor);
IF watchCursorHandle <> NIL THEN
SetCursor(watchCursorHandle^^);
HLock(Handle(vhWindowRelatedInfo));
{--- Update window "exteriors". }
IF resized THEN
BEGIN
vhHorizontalScroll := vhWindowRelatedInfo^^.rHorizontalScrollControl;
vhVerticalScroll := vhWindowRelatedInfo^^.rVerticalScrollControl;
{ HideControl invalidates the control area. It will be }
{ redrawn, though, because everything is redrawn. Thus we }
{ validate it back. (MoveControl would call HideControl, }
{ if we didn't call it by ourselves. Then we would not know }
{ the (automatically) invalidated rectangle.) }
HideControl(vhHorizontalScroll);
vScrollRect := vhHorizontalScroll^^.contrlRect;
ValidRect(vScrollRect);
HideControl(vhVerticalScroll);
vScrollRect := vhVerticalScroll^^.contrlRect;
ValidRect(vScrollRect);
pCalcHorizontalScrollRect(theWindow, vScrollRect);
SizeControl(vhHorizontalScroll, vScrollRect.right - vScrollRect.left, cMagicalWidthOfScrollBars);
MoveControl(vhHorizontalScroll, vScrollRect.left, vScrollRect.top);
ShowControl(vhHorizontalScroll);
pCalcVerticalScrollRect(theWindow, vScrollRect);
SizeControl(vhVerticalScroll, cMagicalWidthOfScrollBars, vScrollRect.bottom - vScrollRect.top);
MoveControl(vhVerticalScroll, vScrollRect.left, vScrollRect.top);
ShowControl(vhVerticalScroll);
pSetScrollBarLimits(theWindow);
END;
DrawControls(theWindow);
pCalcPageNumberRect(theWindow, vScrollRect);
InsetRect(vScrollRect, 1, 1);
EraseRect(vScrollRect);
MoveTo(vScrollRect.left+1, vScrollRect.top+11);
NumToString(
Longint(vhWindowRelatedInfo^^.rPageNumber),
pageNumberAsString
);
NumToString(
Longint(vhWindowRelatedInfo^^.rSpoolFileHeader.pfPgDir.iPages),
lastPageNumberAsString
);
DrawString(
fParametrizeSTR(
cStringPage, {from resource, but if not found, then here}
'Page ^0 of ^1',
pageNumberAsString,
lastPageNumberAsString
)
);
DrawGrowIcon(theWindow);
{--- Update window contents. }
SetOrigin(
GetCtlValue(vhWindowRelatedInfo^^.rHorizontalScrollControl),
GetCtlValue(vhWindowRelatedInfo^^.rVerticalScrollControl)
);
saveClip := NewRgn;
IF saveClip <> NIL THEN
BEGIN
GetClip(saveClip);
pCalcDocumentRect(theWindow, docRect);
ClipRect(docRect); {to save already drawn scroll bars}
docRgn := NewRgn;
IF docRgn <> NIL THEN
GetClip(docRgn);
END; {IF saveClip could be allocated }
CASE vhWindowRelatedInfo^^.rViewMenuSelectionForThisWindow OF
cViewContents:
BEGIN
{ Draw grey around actual document. }
{ (=remove current page drawing area from window clip (=doc area)). }
pageRect := vhWindowRelatedInfo^^.rViewSize[cViewContents];
pageRgn := NewRgn;
RectRgn(
pageRgn,
pageRect
);
theRgn := NewRgn;
DiffRgn(docRgn, pageRgn, theRgn);
{ Grey background. }
PenPat(gray);
PaintRgn(theRgn); {background}
PenPat(black);
{ Drop shadow: frame page; don't draw to top left; }
InsetRect(pageRect, -1, -1);
FrameRect(pageRect);
InsetRect(pageRect, 1, 1);
SetClip(theRgn);
OffsetRect(pageRect, 2, 2);
PenSize(2, 2);
FrameRect(pageRect);
PenSize(1, 1);
{ Page drawing. }
SectRgn(
docRgn,
pageRgn,
theRgn
); {to save everything but page}
SetClip(theRgn);
pUpdateWindowPageContents(
theWindow,
vhWindowRelatedInfo,
vhWindowRelatedInfo^^.rPageNumber,
{needErasing=>} True,
{scalingForScreen=>} True
);
DisposeRgn(theRgn);
DisposeRgn(pageRgn);
END;
OTHERWISE
pUpdateWindowInformation(
theWindow,
vhWindowRelatedInfo,
True {needErasing}
);
END; {CASE}
IF saveClip <> NIL THEN
BEGIN
SetClip(saveClip);
DisposeRgn(saveClip);
IF docRgn <> NIL THEN
DisposeRgn(docRgn);
END; {IF saveClip could be allocated }
SetOrigin(0, 0);
{---}
HUnlock(Handle(vhWindowRelatedInfo));
{ Cursor as an arrow. }
SetCursor(arrow);
END; {pUpdateWindow}
PROCEDURE pChangeViewMenuAccordingToWindow {(theWindow: WindowPtr)} ;
VAR
vhWindowRelatedInfo: thWindowRelatedInfo;
theItem: Integer;
i: Integer;
BEGIN
IF theWindow = NIL THEN
theItem := vViewMenuSelectionDefault
ELSE
BEGIN {get the viewing method of a window}
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
theItem := vhWindowRelatedInfo^^.rViewMenuSelectionForThisWindow;
END;
FOR i:= cViewInformation TO cViewContents DO
CheckItem(vMenu[eView], i, (i=theItem));
END; {pChangeViewMenuAccordingToWindow}
PROCEDURE pChangeSettingsMenuAccordingToWindow {(theWindow: WindowPtr)} ;
VAR
vhWindowRelatedInfo: thWindowRelatedInfo;
usePrinterSpacing: Boolean;
disableFontScaling: Boolean;
BEGIN
IF theWindow = NIL THEN
BEGIN
usePrinterSpacing := vSettingsUsePrinterSpacing;
disableFontScaling := vSettingsDisableFontScaling;
END
ELSE
BEGIN {get the font settings for this window}
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
usePrinterSpacing := vhWindowRelatedInfo^^.rUsePrinterSpacing;
disableFontScaling := vhWindowRelatedInfo^^.rDisableFontScaling;
END;
CheckItem(vMenu[eSettings], cSettingsUsePrinterSpacing, usePrinterSpacing);
CheckItem(vMenu[eSettings], cSettingsDisableFontScaling, disableFontScaling);
END; {pChangeSettingsMenuAccordingToWindow}
PROCEDURE pNormalizePageNumberAndAdjustPageMenu(
vhWindowRelatedInfo: thWindowRelatedInfo
);
VAR
thePageNumber: Integer;
BEGIN
thePageNumber := vhWindowRelatedInfo^^.rPageNumber;
IF vhWindowRelatedInfo^^.rSpoolFileHeader.pfPgDir.iPages <= 1 THEN
BEGIN
thePageNumber := 1;
DisableItem(vMenu[ePage], cPagePrevious);
DisableItem(vMenu[ePage], cPageNext);
DisableItem(vMenu[ePage], cPageFirst);
DisableItem(vMenu[ePage], cPageLast);
END
ELSE IF thePageNumber <= 1 THEN
BEGIN
thePageNumber := 1;
DisableItem(vMenu[ePage], cPagePrevious);
EnableItem(vMenu[ePage], cPageNext);
DisableItem(vMenu[ePage], cPageFirst);
EnableItem(vMenu[ePage], cPageLast);
END
ELSE IF thePageNumber >=
vhWindowRelatedInfo^^.rSpoolFileHeader.pfPgDir.iPages
THEN
BEGIN
thePageNumber := vhWindowRelatedInfo^^.rSpoolFileHeader.pfPgDir.iPages;
EnableItem(vMenu[ePage], cPagePrevious);
DisableItem(vMenu[ePage], cPageNext);
EnableItem(vMenu[ePage], cPageFirst);
DisableItem(vMenu[ePage], cPageLast);
END
ELSE
BEGIN
{thePageNumber is ok}
EnableItem(vMenu[ePage], cPageNext);
EnableItem(vMenu[ePage], cPagePrevious);
EnableItem(vMenu[ePage], cPageFirst);
EnableItem(vMenu[ePage], cPageLast);
END;
vhWindowRelatedInfo^^.rPageNumber := thePageNumber;
END; {pNormalizePageNumberAndAdjustPageMenu}
PROCEDURE pChangePageMenuAccordingToWindow(theWindow: WindowPtr);
VAR
vhWindowRelatedInfo: thWindowRelatedInfo;
pageNumber,
lastPageNumber: Integer;
pageNumberAsString,
lastPageNumberAsString: Str255;
BEGIN
IF theWindow = NIL THEN
BEGIN
pageNumber := 1;
lastPageNumber := 1;
END
ELSE
BEGIN {get the font settings for this window}
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
pNormalizePageNumberAndAdjustPageMenu(vhWindowRelatedInfo);
pageNumber := vhWindowRelatedInfo^^.rPageNumber;
lastPageNumber := vhWindowRelatedInfo^^.rSpoolFileHeader.pfPgDir.iPages;
END;
NumToString(pageNumber, pageNumberAsString);
NumToString(lastPageNumber, lastPageNumberAsString);
SetItem(
vMenu[ePage],
cPagePageNumberItem,
fParametrizeSTR(
cStringPage, {from resource, but if not found, then here}
'Page ^0 of ^1',
pageNumberAsString,
lastPageNumberAsString
)
);
{ Seems to be unnecessary to invalidate page number rectangle }
{ to redraw it. }
END; {pChangePageMenuAccordingToWindow}
FUNCTION fNotExistingOrNotOurs(theWindow: WindowPtr) : Boolean;
BEGIN
IF theWindow = NIL THEN
fNotExistingOrNotOurs := True
ELSE IF WindowPeek(theWindow)^.windowKind <> userKind THEN
fNotExistingOrNotOurs := True
ELSE
fNotExistingOrNotOurs := False;
END; {fNotExistingOrNotOurs}
PROCEDURE pActivateWindow(active: Boolean);
VAR
savePort: WindowPtr;
theWindow: WindowPtr;
aControl: ControlHandle;
BEGIN
GetPort(savePort);
theWindow := savePort;
IF (NOT active) AND (theWindow = FrontWindow) THEN
BEGIN
{ A truly horrendous kludge to overcome a TransSkel deficiency: }
{ When windows are deactivated, the port is not set. }
{ Thus we "back" one window. Fails miserably if for some reason }
{ the deactivated window was not frontmost. }
theWindow := WindowPtr(WindowPeek(theWindow)^.nextWindow); {back one}
IF fNotExistingOrNotOurs(theWindow) THEN
Exit; {no back window}
SetPort(theWindow); {to make for instance ValidRect work}
END;
IF active THEN
BEGIN
pChangeViewMenuAccordingToWindow(theWindow);
pChangeSettingsMenuAccordingToWindow(theWindow);
pChangePageMenuAccordingToWindow(theWindow);
END;
{ Scroll bars etc. }
aControl := WindowPeek(theWindow)^.controlList;
WHILE aControl <> NIL DO
BEGIN
IF active THEN
ShowControl(aControl)
ELSE
BEGIN
HideControl(aControl);
{ HideControl redraws the blank scroll bar. }
HLock(Handle(aControl));
ValidRect(aControl^^.contrlRect); {shouldn't it be """visRgn""" of control??}
HUnlock(Handle(aControl));
END;
aControl := aControl^^.nextControl;
END; {WHILE}
DrawGrowIcon(theWindow);
SetPort(savePort);
{ End of window appearance operations, start of other things. }
{ Inactivate events come before activate events: }
{ thus menus can be disabled/enabled. Primary for desk acc. windows. }
IF active THEN
BEGIN
EnableItem(vMenu[eFile], cFileClose);
EnableItem(vMenu[eFile], cFileCloseAll);
EnableItem(vMenu[eFile], cFilePageSetup);
EnableItem(vMenu[eFile], cFilePageSetupAll);
EnableItem(vMenu[eFile], cFilePrint);
EnableItem(vMenu[eFile], cFilePrintAll);
DisableItem(vMenu[eEdit], cEditUndo);
DisableItem(vMenu[eEdit], cEditCut);
DisableItem(vMenu[eEdit], cEditCopy);
DisableItem(vMenu[eEdit], cEditPaste);
DisableItem(vMenu[eEdit], cEditClear);
EnableItem(vMenu[eView], cViewInformation);
EnableItem(vMenu[eView], cViewContents);
EnableItem(vMenu[eView], cViewScalePreview);
EnableItem(vMenu[eSettings], cSettingsUsePrinterSpacing);
EnableItem(vMenu[eSettings], cSettingsDisableFontScaling);
{ next, previous, first, last are enabled in change page menu above}
EnableItem(vMenu[ePage], cPageGotoPage);
END
ELSE
BEGIN
DisableItem(vMenu[eFile], cFileClose);
DisableItem(vMenu[eFile], cFileCloseAll);
DisableItem(vMenu[eFile], cFilePageSetup);
DisableItem(vMenu[eFile], cFilePageSetupAll);
DisableItem(vMenu[eFile], cFilePrint);
DisableItem(vMenu[eFile], cFilePrintAll);
EnableItem(vMenu[eEdit], cEditUndo);
EnableItem(vMenu[eEdit], cEditCut);
EnableItem(vMenu[eEdit], cEditCopy);
EnableItem(vMenu[eEdit], cEditPaste);
EnableItem(vMenu[eEdit], cEditClear);
DisableItem(vMenu[eView], cViewInformation);
DisableItem(vMenu[eView], cViewContents);
DisableItem(vMenu[eView], cViewScalePreview);
DisableItem(vMenu[eSettings], cSettingsUsePrinterSpacing);
DisableItem(vMenu[eSettings], cSettingsDisableFontScaling);
DisableItem(vMenu[ePage], cPageNext);
DisableItem(vMenu[ePage], cPagePrevious);
DisableItem(vMenu[ePage], cPageFirst);
DisableItem(vMenu[ePage], cPageLast);
DisableItem(vMenu[ePage], cPageGotoPage);
END;
END; {pActivateWindow}
PROCEDURE pCallTransSkelToRemoveWindow(theWindow: WindowPtr);
BEGIN
SkelRmveWind(theWindow);
vNumberOfOurOpenWindows := vNumberOfOurOpenWindows - 1;
IF vNumberOfOurOpenWindows <= 0 THEN
pMenusToState(eNoOurWindowsOpen);
END; {pCallTransSkelToRemoveWindow}
PROCEDURE pCloseWindow; {for TransSkel}
VAR
theWindow: WindowPtr;
BEGIN
GetPort(theWindow);
IF fNotExistingOrNotOurs(theWindow) THEN
Exit;
pCallTransSkelToRemoveWindow(theWindow);
END; {pCloseWindow}
PROCEDURE pDoClose; {for File menu}
VAR
theWindow: WindowPtr;
BEGIN
theWindow := FrontWindow;
{For symmetry we shoud call GetPort,}
{but FrontWindow tells us when there are none of them.}
IF fNotExistingOrNotOurs(theWindow) THEN
Exit;
pCallTransSkelToRemoveWindow(theWindow);
END; {pDoClose}
PROCEDURE pDoCloseAll;
VAR
theWindow: WindowPtr;
BEGIN
theWindow := FrontWindow;
WHILE theWindow <> NIL DO
BEGIN
IF WindowPeek(theWindow)^.windowKind = userKind THEN
pCallTransSkelToRemoveWindow(theWindow);
theWindow := WindowPtr(WindowPeek(theWindow)^.nextWindow);
END; {WHILE}
END; {pDoCloseAll}
PROCEDURE pOpenWindowByName(
theName: Str255;
theVRefNum: Integer
);
VAR
theWindow: WindowPtr;
vSFReply: SFReply;
BEGIN
{ Set the SFReply just as if a SFGetFile would have set.}
vSFReply.fName := theName;
vSFReply.vRefNum := theVRefNum;
vSFReply.good := True;
IF NOT fCreateWindow(theWindow, vSFReply) THEN
Exit;
IF NOT SkelWindow(
theWindow,
@pMouseInWindow,
NIL, {no keyboard handling}
@pUpdateWindow,
@pActivateWindow,
@pCloseWindow,
@pDisposeAllStructuresRelatedToCurrentWindow,
NIL, {no idle procedure for this window}
True {idle procedure need to be called only when this window is topmost}
)
THEN
BEGIN
pErrorAlert(cAlertNoMemoryForWindows);
pDisposeAllStructuresRelatedToThisWindow(theWindow);
DisposeWindow(theWindow);
Exit;
END;
END; {pOpenWindowByName}
PROCEDURE pOpenWindowByAskingUserTheName;
VAR
theWindow: WindowPtr;
where: Point;
prompt: Str255;
allowedFileTypes: SFTypeList;
vSFReply: SFReply;
BEGIN
where.v := 70;
where.h := 70;
prompt := '';
allowedFileTypes[0] := 'PFIL';
SFGetFile(
where,
prompt,
NIL, {fileFilter}
1, {one allowed file type}
allowedFileTypes,
NIL, {dlgHook}
vSFReply
);
IF NOT vSFReply.good THEN
Exit;
IF NOT fCreateWindow(theWindow, vSFReply) THEN
Exit;
IF NOT SkelWindow(
theWindow,
@pMouseInWindow, {no mouse handling}
NIL, {no keyboard handling}
@pUpdateWindow,
@pActivateWindow,
@pCloseWindow,
@pDisposeAllStructuresRelatedToCurrentWindow,
NIL, {no idle procedure for this window}
True {idle procedure need to be called only when this window is topmost}
)
THEN
BEGIN
pErrorAlert(cAlertNoMemoryForWindows);
pDisposeAllStructuresRelatedToThisWindow(theWindow);
DisposeWindow(theWindow);
Exit;
END;
END; {pOpenWindowByAskingUserTheName}
FUNCTION fOurPageSetup(theWindow: WindowPtr) : Boolean;
VAR
vhWindowRelatedInfo: thWindowRelatedInfo;
wasItChanged: Boolean;
doIt: Boolean;
BEGIN
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
{ From Tech Note 161: }
PrOpen;
IF PrError = noErr THEN
BEGIN
wasItChanged := PrValidate(THPrint(vhWindowRelatedInfo));
doIt := PrStlDialog(THPrint(vhWindowRelatedInfo));
IF PrError <> noErr THEN
pPrintErrorAlert(cAlertPrintError, PrError)
ELSE
; {do whatever you need to}
END
ELSE
pPrintErrorAlert(cAlertPrintError, PrError);
PrClose;
fOurPageSetup := doIt AND (PrError = noErr);
END; {fOurPageSetup}
FUNCTION fOurPrintWindow(
theWindow: WindowPtr;
doYouWishToPresentJobDialog: Boolean
) : Boolean;
LABEL
closeDriver;
VAR
vhWindowRelatedInfo: thWindowRelatedInfo;
savePort: GrafPtr;
wasItChanged: Boolean;
doIt: Boolean;
printingGrafPort: TPPrPort;
myFirst,
myLast,
pageNumber: Integer;
dummyStatusRecord: TPrStatus;
BEGIN
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
GetPort(savePort);
PrOpen; {open up printer resource file}
IF PrError <> noErr THEN
BEGIN
pPrintErrorAlert(cAlertPrintError, PrError);
doIt := False;
GOTO closeDriver;
END;
wasItChanged := PrValidate(THPrint(vhWindowRelatedInfo));
IF doYouWishToPresentJobDialog THEN
BEGIN
doIt := PrJobDialog(THPrint(vhWindowRelatedInfo));
IF NOT doIt THEN
GOTO closeDriver;
END
ELSE
doIt := True;
printingGrafPort := PrOpenDoc( { open printing grafPort }
THPrint(vhWindowRelatedInfo),
NIL,
NIL
);
myFirst := THPrint(vhWindowRelatedInfo)^^.prJob.iFstPage;
myLast := THPrint(vhWindowRelatedInfo)^^.prJob.iLstPage;
IF myLast > vhWindowRelatedInfo^^.rSpoolFileHeader.pfPgDir.iPages THEN
myLast := vhWindowRelatedInfo^^.rSpoolFileHeader.pfPgDir.iPages;
THPrint(vhWindowRelatedInfo)^^.prJob.iFstPage := 1;
THPrint(vhWindowRelatedInfo)^^.prJob.iLstPage := iPrPgMax;
FOR pageNumber:=myFirst TO myLast DO {page loop}
IF PrError = noErr THEN
BEGIN
PrOpenPage(printingGrafPort, NIL);
IF PrError = noErr THEN
BEGIN
HLock(Handle(vhWindowRelatedInfo));
pUpdateWindowPageContents(
GrafPtr(printingGrafPort),
vhWindowRelatedInfo,
pageNumber,
{needErasing=>} False, {not on paper}
{scalingForScreen=>} False {always original size}
); {draw page with QuickDraw}
HUnlock(Handle(vhWindowRelatedInfo));
END;
PrClosePage(printingGrafPort);
END;
PrCloseDoc(printingGrafPort);
IF (THPrint(vhWindowRelatedInfo)^^.prJob.bJDocLoop = bSpoolLoop)
AND (PrError = noErr) THEN
BEGIN
{ MySwapOutProc; swap out code and data, if necessary }
PrPicFile(
THPrint(vhWindowRelatedInfo),
NIL,
NIL,
NIL,
dummyStatusRecord
);
END;
IF PrError <> noErr THEN
pPrintErrorAlert(cAlertPrintError, PrError);
closeDriver:
PrClose;
SetPort(savePort);
fOurPrintWindow := doIt;
END; {fOurPrintWindow}
PROCEDURE pCopyThePrintRecord(source, destination: thWindowRelatedInfo);
BEGIN
destination^^.rSpoolFileHeader.Print := source^^.rSpoolFileHeader.Print;
END; {pCopyThePrintRecord}
PROCEDURE pDoPageSetupAll;
VAR
theWindow: WindowPtr;
doIt: Boolean;
BEGIN
theWindow := FrontWindow;
IF fNotExistingOrNotOurs(theWindow) THEN
Exit;
doIt := fOurPageSetup(theWindow);
IF doIt THEN
BEGIN
theWindow := WindowPtr(WindowPeek(theWindow)^.nextWindow);
WHILE theWindow <> NIL DO
BEGIN
IF WindowPeek(theWindow)^.windowKind = userKind THEN
pCopyThePrintRecord(
thWindowRelatedInfo(GetWRefCon(FrontWindow)),
thWindowRelatedInfo(GetWRefCon(theWindow))
);
theWindow := WindowPtr(WindowPeek(theWindow)^.nextWindow);
END; {WHILE}
END; {IF OK clicked}
END; {pDoPageSetupAll}
PROCEDURE pDoPrintAll;
VAR
theWindow: WindowPtr;
doIt: Boolean;
BEGIN
theWindow := FrontWindow;
IF fNotExistingOrNotOurs(theWindow) THEN
Exit;
doIt := fOurPrintWindow(theWindow, {job dialog=>} True);
IF doIt THEN
BEGIN
theWindow := WindowPtr(WindowPeek(theWindow)^.nextWindow);
WHILE theWindow <> NIL DO
BEGIN
IF WindowPeek(theWindow)^.windowKind = userKind THEN
BEGIN
BEGIN { use Job Merge }
PrOpen;
IF PrError = noErr THEN
BEGIN
PrJobMerge(
THPrint(GetWRefCon(FrontWindow)),
THPrint(GetWRefCon(theWindow))
);
END
ELSE
pPrintErrorAlert(cAlertPrintError, PrError);
PrClose;
END; { use Job Merge }
doIt := fOurPrintWindow(theWindow, {job dialog=>} False);
END; {IF our window}
theWindow := WindowPtr(WindowPeek(theWindow)^.nextWindow);
END; {WHILE}
END; {IF OK clicked}
END; {pDoPrintAll}
PROCEDURE pDoFileMenu(theItem: Integer);
VAR
theWindow: WindowPtr;
doIt: Boolean;
BEGIN
CASE theItem OF
cFileOpen:
pOpenWindowByAskingUserTheName;
cFileClose:
pDoClose;
cFileCloseAll:
pDoCloseAll;
cFilePageSetup:
BEGIN
theWindow := FrontWindow;
IF fNotExistingOrNotOurs(theWindow) THEN
Exit;
doIt := fOurPageSetup(theWindow);
END; {CASE page setup}
cFilePageSetupAll:
pDoPageSetupAll;
cFilePrint:
BEGIN
theWindow := FrontWindow;
IF fNotExistingOrNotOurs(theWindow) THEN
Exit;
doIt := fOurPrintWindow(theWindow, True {job dialog} );
END; {CASE print}
cFilePrintAll:
pDoPrintAll;
OTHERWISE
SkelWhoa;
END; {CASE}
END; {pDoFileMenu}
PROCEDURE pDoEditMenu(theItem: Integer);
BEGIN
END; {pDoEditMenu}
PROCEDURE pFrameButton(
theDialog: DialogPtr;
theItem: Integer
);
VAR
savePort: GrafPtr;
itemType: Integer;
itemHandle: Handle;
itemBBox: Rect;
integerAsString: Str255;
integerAsLongint: Longint;
BEGIN
GetPort(savePort);
SetPort(theDialog);
GetDItem(theDialog, theItem, itemType, itemHandle, itemBBox);
PenSize(3, 3);
InsetRect(itemBBox, -4, -4);
FrameRoundRect(itemBBox, 16, 16);
SetPort(savePort);
END; {pFrameButton}
PROCEDURE pSetTextDITFromInteger(
theDialog: DialogPtr;
theItem: Integer;
theInteger: Integer
);
VAR
itemType: Integer;
itemHandle: Handle;
itemBBox: Rect;
integerAsString: Str255;
BEGIN
GetDItem(theDialog, theItem, itemType, itemHandle, itemBBox);
itemType := itemType MOD itemDisable;
IF (itemType = statText) OR (itemType = editText) THEN
BEGIN
NumToString(theInteger, integerAsString);
SetIText(itemHandle, integerAsString);
END;
END; {pSetTextDITFromInteger}
FUNCTION fGetTextDITAsInteger(
theDialog: DialogPtr;
theItem: Integer
) : Integer;
VAR
itemType: Integer;
itemHandle: Handle;
itemBBox: Rect;
integerAsString: Str255;
integerAsLongint: Longint;
BEGIN
GetDItem(theDialog, theItem, itemType, itemHandle, itemBBox);
itemType := itemType MOD itemDisable;
IF (itemType = statText) OR (itemType = editText) THEN
BEGIN
GetIText(itemHandle, integerAsString);
StringToNum(integerAsString, integerAsLongint);
fGetTextDITAsInteger := integerAsLongint;
END
ELSE
fGetTextDITAsInteger := 0;
END; {fGetTextDITAsInteger}
PROCEDURE pDoViewMenu(theItem: Integer);
VAR
theWindow: WindowPtr;
vhWindowRelatedInfo: thWindowRelatedInfo;
i: Integer;
theDialog: DialogPtr;
itemHit: Integer;
FUNCTION fCheckAndCorrected(VAR percentage: Integer) : Boolean;
VAR
percentageAsString: Str255;
explanation: Str255;
buttonClicked: Integer;
BEGIN
buttonClicked := cOkButton;
NumToString(Longint(percentage), percentageAsString);
IF percentage < 5 THEN
BEGIN
explanation := fParametrizeSTR(
cStringUnderMinimum,
'The value ╥^0╙ is replaced by the smallest allowed minimum of 5%.',
percentageAsString,
''
);
ParamText(explanation, '', '', '');
buttonClicked := Alert(cAlertScalingPercentageOutOfBounds, NIL);
IF buttonClicked = cOkButton THEN
percentage := 5;
END
ELSE IF percentage >3200 THEN
BEGIN
explanation := fParametrizeSTR(
cStringOverMaximum,
'The value ╥^0╙ is replaced by the largest allowed maximum of 3200%.',
percentageAsString,
''
);
ParamText(explanation, '', '', '');
buttonClicked := Alert(cAlertScalingPercentageOutOfBounds, NIL);
IF buttonClicked = cOkButton THEN
percentage := 3200;
END
ELSE
ResetAlrtStage; {reward for right answer :-) }
fCheckAndCorrected := (buttonClicked = cOkButton);
END; {fCheckAndCorrected}
BEGIN
theWindow := FrontWindow;
CASE theItem OF
cViewInformation,
cViewContents:
BEGIN
IF fNotExistingOrNotOurs(theWindow) THEN
vViewMenuSelectionDefault := theItem
ELSE
BEGIN {set the viewing method of a window}
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
vhWindowRelatedInfo^^.rViewMenuSelectionForThisWindow := theItem;
pSetScrollBarLimits(theWindow);
pInvalidateAllOfWindow(theWindow);
END;
FOR i:= cViewInformation TO cViewContents DO
CheckItem(vMenu[eView], i, (i=theItem));
END;
cViewScalePreview:
BEGIN {set the scaling percentage of a window}
theDialog := GetNewDialog(cDialogScalePreview, NIL, WindowPtr(-1));
IF theDialog <> NIL THEN
BEGIN
pFrameButton(theDialog, cOkButton);
IF fNotExistingOrNotOurs(theWindow) THEN
pSetTextDITFromInteger( {from global defaults}
theDialog,
cDITScalePercentage,
vViewScalePercentageDefault
)
ELSE
BEGIN
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
pSetTextDITFromInteger( {from window}
theDialog,
cDITScalePercentage,
vhWindowRelatedInfo^^.rViewScalePreviewPercentage
)
END;
SelIText(theDialog, cDITScalePercentage, 0, 32767); {preselect it}
ModalDialog( {filterProc=>} NIL, itemHit);
IF itemHit = cOkButton THEN
BEGIN
i := fGetTextDITAsInteger(theDialog, cDITScalePercentage);
DisposDialog(theDialog); {hide dialog before possible alert}
IF fCheckAndCorrected(i) THEN
BEGIN
IF fNotExistingOrNotOurs(theWindow) THEN
BEGIN
vViewScalePercentageDefault := i;
END
ELSE
BEGIN {set the viewing method of a window}
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
vhWindowRelatedInfo^^.rViewScalePreviewPercentage := i;
pRetitleWindow(theWindow); {to reflect scaling in title}
pCalcScaledPageDrawingRect(vhWindowRelatedInfo);
pSetScrollBarLimits(theWindow);
pInvalidateAllOfWindow(theWindow);
END;
END; {IF entered number ok}
END {IF OK clicked}
ELSE
DisposDialog(theDialog);
END; {IF dialog not NIL}
END; {case Scale Preview}
END; {CASE}
END; {pDoViewMenu}
PROCEDURE pDoSettingsMenu(theItem: Integer);
VAR
theWindow: WindowPtr;
vhWindowRelatedInfo: thWindowRelatedInfo;
usePrinterSpacing: Boolean;
disableFontScaling: Boolean;
BEGIN
theWindow := FrontWindow;
IF fNotExistingOrNotOurs(theWindow) THEN
BEGIN
usePrinterSpacing := vSettingsUsePrinterSpacing;
disableFontScaling := vSettingsDisableFontScaling;
CASE theItem OF
cSettingsUsePrinterSpacing:
BEGIN
usePrinterSpacing := NOT usePrinterSpacing;
vSettingsUsePrinterSpacing := usePrinterSpacing;
END;
cSettingsDisableFontScaling:
BEGIN
disableFontScaling := NOT disableFontScaling;
vSettingsDisableFontScaling := disableFontScaling;
END;
END; {CASE}
END
ELSE
BEGIN {set the viewing method of a window}
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
usePrinterSpacing := vhWindowRelatedInfo^^.rUsePrinterSpacing;
disableFontScaling := vhWindowRelatedInfo^^.rDisableFontScaling;
CASE theItem OF
cSettingsUsePrinterSpacing:
BEGIN
usePrinterSpacing := NOT usePrinterSpacing;
vhWindowRelatedInfo^^.rUsePrinterSpacing := usePrinterSpacing;
END;
cSettingsDisableFontScaling:
BEGIN
disableFontScaling := NOT disableFontScaling;
vhWindowRelatedInfo^^.rDisableFontScaling := disableFontScaling;
END;
END; {CASE}
pInvalidateAllOfWindow(theWindow);
END;
CheckItem(vMenu[eSettings], cSettingsUsePrinterSpacing, usePrinterSpacing);
CheckItem(vMenu[eSettings], cSettingsDisableFontScaling, disableFontScaling);
END; {pDoSettingsMenu}
PROCEDURE pDoPageMenu(theItem: Integer);
VAR
theWindow: WindowPtr;
vhWindowRelatedInfo: thWindowRelatedInfo;
oldPageNumber: Integer;
newPageNumber: Integer;
theDialog: DialogPtr;
itemHit: Integer;
BEGIN
theWindow := FrontWindow;
IF fNotExistingOrNotOurs(theWindow) THEN
Exit;
vhWindowRelatedInfo := thWindowRelatedInfo(GetWRefCon(theWindow));
oldPageNumber := vhWindowRelatedInfo^^.rPageNumber;
CASE theItem OF
cPagePrevious:
newPageNumber := oldPageNumber - 1;
cPageNext:
newPageNumber := oldPageNumber + 1;
cPageFirst:
newPageNumber := 1;
cPageLast:
newPageNumber := vhWindowRelatedInfo^^.rSpoolFileHeader.pfPgDir.iPages;
cPageGotoPage:
BEGIN
theDialog := GetNewDialog(cDialogGotoPage, NIL, WindowPtr(-1));
IF theDialog <> NIL THEN
BEGIN
pFrameButton(theDialog, cOkButton);
pSetTextDITFromInteger( {from window}
theDialog,
cDITPageNumber,
vhWindowRelatedInfo^^.rPageNumber
);
SelIText(theDialog, cDITPageNumber, 0, 32767); {preselect it}
ModalDialog( {filterProc=>} NIL, itemHit);
IF itemHit = cOkButton THEN
newPageNumber :=
fGetTextDITAsInteger(theDialog, cDITPageNumber)
ELSE
newPageNumber := oldPageNumber;
DisposDialog(theDialog);
END; {IF dialog not NIL}
END; {case Goto page}
OTHERWISE {cPagePageNumberItem:}
;
END; {CASE}
vhWindowRelatedInfo^^.rPageNumber := newPageNumber;
pChangePageMenuAccordingToWindow(theWindow);
{Procedure 'pChangePageMenuAccordingToWindow' calls}
{'pNormalizePageNumberAndAdjustPageMenu'.}
{ If page number really changes, then the whole window needs to be redrawn. }
IF oldPageNumber <> vhWindowRelatedInfo^^.rPageNumber THEN
pInvalidateAllOfWindow(theWindow);
END; {pDoPageMenu}
BEGIN {BatchPrint}
{ Initialize TransSkel with 10 MoreMasters and no GrowZone procedure. }
SkelInit(10, NIL);
CouldAlert(cAlertNoMemoryForWindows);
CouldAlert(cAlertFileError);
CouldAlert(cAlertPrintError);
{ Desk accessories into standard Apple menu. }
hString := GetString(cStringAboutBatchPrint);
IF hString = NIL THEN
SkelApple('About BatchPrint╔', @pDoAboutBatchPrint)
ELSE
BEGIN
HLock(Handle(hString));
SkelApple(hString^^, @pDoAboutBatchPrint);
HUnlock(Handle(hString));
ReleaseResource(Handle(hString));
END;
{ Fetch menus from resources. }
FOR vMenuEnumeration := eFile TO ePage DO
vMenu[vMenuEnumeration] := GetMenu(cMenuFirstId+Ord(vMenuEnumeration));
successful := SkelMenu(vMenu[eFile], @pDoFileMenu, NIL, False);
successful := SkelMenu(vMenu[eEdit], @pDoEditMenu, NIL, False);
successful := SkelMenu(vMenu[eView], @pDoViewMenu, NIL, False);
successful := SkelMenu(vMenu[eSettings], @pDoSettingsMenu, NIL, False);
successful := SkelMenu(vMenu[ePage], @pDoPageMenu, NIL, True);
{ Default viewing method. }
vViewMenuSelectionDefault := cViewInformation;
vViewScalePercentageDefault := cViewScalePercentageDefault;
pChangeViewMenuAccordingToWindow(NIL);
{ Check for 128K ROMs. }
Environs(romVersion, machineType);
vHas128KROMs := (romVersion >= 117); {IM IV-236}
IF NOT vHas128KROMs THEN
BEGIN
DisableItem(vMenu[eSettings], 0); {all of it}
DrawMenuBar;
END;
{ Defaults for font manager behavior. }
vSettingsUsePrinterSpacing := False;
vSettingsDisableFontScaling := False;
pChangeSettingsMenuAccordingToWindow(NIL);
{ Default page number. }
pChangePageMenuAccordingToWindow(NIL);
vNumberOfOurOpenWindows := 0;
pMenusToState(eNoOurWindowsOpen);
{ Check for messages from the Finder. }
CountAppFiles(vWhatFinderToldUsToDo, vNumberOfAppFiles);
IF vNumberOfAppFiles > 0 THEN
BEGIN
{ Open all the files. }
FOR i:=1 TO vNumberOfAppFiles DO
BEGIN
GetAppFiles(i, theAppFile);
IF theAppFile.fType = 'PFIL' THEN
pOpenWindowByName(theAppFile.fName, theAppFile.vRefNum);
ClrAppFiles(i); {as instructed by IM II-58}
END; {FOR each file}
{ If requested to print, print immediately and exit. }
IF vWhatFinderToldUsToDo = appPrint THEN
BEGIN
pDoPrintAll;
SkelWhoa;
END;
END; {IF files from Finder}
{ Perform main event loop until 'Quit' from 'File' menu is selected and 'SkelWhoa' called. }
SkelMain;
{ TransSkel clean up. }
SkelClobber;
END. {BatchPrint}